/* __ __ __ __ __ ___
* \ \ / / \ \ / / __/
* \ \/ / /\ \ \/ / /
* \____/__/ \__\____/__/.ɪᴏ
* ᶜᵒᵖʸʳᶦᵍʰᵗ ᵇʸ ᵛᵃᵛʳ ⁻ ˡᶦᶜᵉⁿˢᵉᵈ ᵘⁿᵈᵉʳ ᵗʰᵉ ᵃᵖᵃᶜʰᵉ ˡᶦᶜᵉⁿˢᵉ ᵛᵉʳˢᶦᵒⁿ ᵗʷᵒ ᵈᵒᵗ ᶻᵉʳᵒ
*/
package io.vavr.collection;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import java.util.*;
import java.util.function.Function;
import java.util.function.UnaryOperator;
import static io.vavr.collection.JavaConvertersTest.ChangePolicy.IMMUTABLE;
import static io.vavr.collection.JavaConvertersTest.ChangePolicy.MUTABLE;
import static io.vavr.collection.JavaConvertersTest.ElementNullability.NON_NULLABLE;
import static io.vavr.collection.JavaConvertersTest.ElementNullability.NULLABLE;
import static io.vavr.collection.JavaConvertersTest.ElementType.FIXED;
import static io.vavr.collection.JavaConvertersTest.ElementType.GENERIC;
import static java.util.Arrays.asList;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
@RunWith(Parameterized.class)
public class JavaConvertersTest {
@SuppressWarnings("unchecked")
@Parameterized.Parameters(name = "{index}: {0} [{2}]")
public static java.util.Collection<Object[]> data() {
return asList(new Object[][] {
// -- immutable classes
{ "java.util.Arrays$ArrayList", new ListFactory(java.util.Arrays::asList), IMMUTABLE, GENERIC, NULLABLE },
{ Array.class.getName(), new ListFactory(ts -> Array.of(ts).asJava()), IMMUTABLE, GENERIC, NULLABLE },
{ CharSeq.class.getName(), new ListFactory(ts -> (java.util.List<Object>) (Object) CharSeq.ofAll((List<Character>) (Object) (List.of(ts))).asJava()), IMMUTABLE, FIXED, NON_NULLABLE },
{ List.class.getName(), new ListFactory(ts -> List.of(ts).asJava()), IMMUTABLE, GENERIC, NULLABLE },
{ Queue.class.getName(), new ListFactory(ts -> Queue.of(ts).asJava()), IMMUTABLE, GENERIC, NULLABLE },
{ Stream.class.getName(), new ListFactory(ts -> Stream.of(ts).asJava()), IMMUTABLE, GENERIC, NULLABLE },
{ Vector.class.getName(), new ListFactory(ts -> Vector.of(ts).asJava()), IMMUTABLE, GENERIC, NULLABLE },
// -- mutable classes
{ java.util.ArrayList.class.getName(), new ListFactory(ts -> {
final java.util.List<Object> list = new java.util.ArrayList<>();
java.util.Collections.addAll(list, ts);
return list;
}), MUTABLE, GENERIC, NULLABLE },
{ Array.class.getName(), new ListFactory(ts -> Array.of(ts).asJavaMutable()), MUTABLE, GENERIC, NULLABLE },
{ CharSeq.class.getName(), new ListFactory(ts -> (java.util.List<Object>) (Object) CharSeq.ofAll((List<Character>) (Object) (List.of(ts))).asJavaMutable()), MUTABLE, FIXED, NON_NULLABLE },
{ List.class.getName(), new ListFactory(ts -> List.of(ts).asJavaMutable()), MUTABLE, GENERIC, NULLABLE },
{ Queue.class.getName(), new ListFactory(ts -> Queue.of(ts).asJavaMutable()), MUTABLE, GENERIC, NULLABLE },
{ Stream.class.getName(), new ListFactory(ts -> Stream.of(ts).asJavaMutable()), MUTABLE, GENERIC, NULLABLE },
{ Vector.class.getName(), new ListFactory(ts -> Vector.of(ts).asJavaMutable()), MUTABLE, GENERIC, NULLABLE }
});
}
private final ListFactory listFactory;
private final ChangePolicy changePolicy;
private final ElementType elementType;
private final ElementNullability elementNullability;
public JavaConvertersTest(String name, ListFactory listFactory, ChangePolicy changePolicy, ElementType elementType, ElementNullability elementNullability) {
this.listFactory = listFactory;
this.changePolicy = changePolicy;
this.elementType = elementType;
this.elementNullability = elementNullability;
}
@SuppressWarnings("unchecked")
private <T> java.util.List<T> empty() {
return listFactory.of();
}
@SuppressWarnings("unchecked")
private <T> java.util.List<T> ofNull() {
return listFactory.of((T) null);
}
@SuppressWarnings("unchecked")
private <T> java.util.List<T> of(T t) {
return listFactory.of(t);
}
@SuppressWarnings("varargs")
@SafeVarargs
private final <T> java.util.List<T> of(T... ts) {
return listFactory.of(ts);
}
// -- add(T)
@Test
public void shouldAddElementToEmptyListView() {
ifSupported(() -> {
final java.util.List<Character> list = empty();
assertThat(list.add('1')).isTrue();
assertThat(list).isEqualTo(asList('1'));
});
}
@Test
public void shouldAddElementToEndOfNonEmptyListView() {
ifSupported(() -> {
final java.util.List<Character> list = of('1');
assertThat(list.add('2')).isTrue();
assertThat(list).isEqualTo(asList('1', '2'));
});
}
@Test
public void shouldAddSubtypeToEndOfNonEmptyListView() {
abstract class A {
@Override
public final int hashCode() {
return 0;
}
}
final class B extends A {
@Override
public boolean equals(Object o) {
return o instanceof B;
}
}
final class C extends A {
@Override
public boolean equals(Object o) {
return o instanceof C;
}
}
if (elementType == GENERIC) {
ifSupported(() -> {
final java.util.List<A> list = of(new B());
assertThat(list.add(new C())).isTrue();
assertThat(list).isEqualTo(asList(new B(), new C()));
});
}
}
@Test
public void shouldAddNull() {
if (elementNullability == NULLABLE) {
ifSupported(() -> {
final java.util.List<Character> list = empty();
assertThat(list.add(null)).isTrue();
assertThat(list).isEqualTo(asList((Object) null));
});
}
}
@Test
public void shouldAddSelf() {
if (elementType == GENERIC) {
ifSupported(() -> {
final java.util.List<Object> list = empty();
assertThat(list.add(list)).isTrue();
assertThat(list).isEqualTo(list);
});
}
}
// -- add(int, T)
@Test
public void shouldThrowWhenAddingElementAtNegativeIndexToEmpty() {
ifSupported(() -> empty().add(-1, null), IndexOutOfBoundsException.class);
}
@Test
public void shouldThrowWhenAddingElementAtNonExistingIndexToEmpty() {
ifSupported(() -> empty().add(1, null), IndexOutOfBoundsException.class);
}
@Test
public void shouldThrowWhenAddingElementAtNegativeIndexToNonEmpty() {
ifSupported(() -> of('1').add(-1, null), IndexOutOfBoundsException.class);
}
@Test
public void shouldThrowWhenAddingElementAtNonExistingIndexToNonEmpty() {
ifSupported(() -> {
final java.util.List<Character> list = of('1');
// should throw for eagerly evaluated collections
list.add(2, null);
// afterburner for lazy persistent collections
list.size();
}, IndexOutOfBoundsException.class);
}
@Test
public void shouldAddNullToEmptyAtIndex0() {
if (elementNullability == NULLABLE) {
ifSupported(() -> {
final java.util.List<Character> list = empty();
list.add(0, null);
assertThat(list).isEqualTo(asList((Object) null));
});
}
}
@Test
public void shouldAddNonNullToEmptyAtIndex0() {
ifSupported(() -> {
final java.util.List<Character> list = empty();
list.add(0, '1');
assertThat(list).isEqualTo(asList('1'));
});
}
@Test
public void shouldAddElementAtSizeIndexToNonEmpty() {
ifSupported(() -> {
final java.util.List<Character> list = of('1');
list.add(1, '2');
assertThat(list).isEqualTo(asList('1', '2'));
});
}
// -- addAll(Collection)
@Test(expected = NullPointerException.class)
public void shouldThrowNPEWhenAddingAllNullCollectionToEmpty() {
empty().addAll(null);
}
@Test(expected = NullPointerException.class)
public void shouldThrowNPEWhenAddingAllNullCollectionToNonEmpty() {
of('1').addAll(null);
}
@Test
public void shouldReturnFalseIfAddAllEmptyToEmpty() {
ifSupported(() -> {
final java.util.List<Character> list = empty();
final java.util.List<Character> javaList = asList();
assertThat(list.addAll(javaList)).isFalse();
assertThat(list).isEqualTo(javaList);
});
}
@Test
public void shouldReturnFalseIfAddAllEmptyToNonEmpty() {
ifSupported(() -> {
final java.util.List<Character> list = of('1');
assertThat(list.addAll(asList())).isFalse();
assertThat(list).isEqualTo(of('1'));
});
}
@Test
public void shouldReturnTrueIfAddAllNonEmptyToEmpty() {
ifSupported(() -> {
final java.util.List<Character> list = empty();
final java.util.List<Character> javaList = asList('1');
assertThat(list.addAll(javaList)).isTrue();
assertThat(list).isEqualTo(javaList);
});
}
@Test
public void shouldReturnTrueIfAddAllNonEmptyToNonEmpty() {
ifSupported(() -> {
final java.util.List<Character> list = of('1', '2', '3');
assertThat(list.addAll(asList('1', '2', '3'))).isTrue();
assertThat(list).isEqualTo(asList('1', '2', '3', '1', '2', '3'));
});
}
// -- addAll(int, Collection)
@Test
public void shouldThrowNPEWhenAddingAllNullCollectionAtFirstIndexToEmpty() {
assertThatThrownBy(() -> empty().addAll(0, null))
.isInstanceOf(NullPointerException.class);
}
@Test
public void shouldThrowNPEWhenAddingAllNullCollectionAtFirstIndexToNonEmpty() {
assertThatThrownBy(() -> of('1').addAll(0, null))
.isInstanceOf(NullPointerException.class);
}
@Test
public void shouldThrowWhenAddingAllCollectionElementsAtNegativeIndexToEmpty() {
ifSupported(() -> empty().addAll(-1, asList('1', '2', '3')), IndexOutOfBoundsException.class);
}
@Test
public void shouldThrowWhenAddingAllCollectionElementsAtNonExistingIndexToEmpty() {
ifSupported(() -> empty().addAll(1, asList('1', '2', '3')), IndexOutOfBoundsException.class);
}
@Test
public void shouldThrowWhenAddingAllCollectionElementsAtNegativeIndexToNonEmpty() {
ifSupported(() -> of('1').addAll(-1, asList('1', '2', '3')), IndexOutOfBoundsException.class);
}
@Test
public void shouldThrowWhenAddingAllCollectionElementsAtNonExistingIndexToNonEmpty() {
ifSupported(() -> {
final java.util.List<Character> list = of('1');
// should throw for eagerly evaluated collections
list.addAll(2, asList('1', '2', '3'));
// afterburner for lazy persistent collections
list.size();
}, IndexOutOfBoundsException.class);
}
@Test
public void shouldAddAllCollectionElementsAtFirstIndexToNonEmpty() {
ifSupported(() -> {
final java.util.List<Character> list = of('4');
assertThat(list.addAll(0, asList('1', '2', '3'))).isTrue();
assertThat(list).isEqualTo(asList('1', '2', '3', '4'));
});
}
@Test
public void shouldAddAllCollectionElementsAtSizeIndexToEmpty() {
ifSupported(() -> {
final java.util.List<Character> list = empty();
final java.util.List<Character> javaList = asList('1', '2', '3');
assertThat(list.addAll(0, javaList)).isTrue();
assertThat(list).isEqualTo(javaList);
});
}
@Test
public void shouldAddAllCollectionElementsAtSizeIndexToNonEmpty() {
ifSupported(() -> {
final java.util.List<Character> list = of('1');
assertThat(list.addAll(1, asList('2', '3'))).isTrue();
assertThat(list).isEqualTo(of('1', '2', '3'));
});
}
// -- clear()
@Test
public void shouldThrowWhenCallingClearOnEmpty() {
final java.util.List<Character> empty = empty();
empty.clear();
assertThat(empty).isEqualTo(asList());
}
@Test
public void shouldThrowWhenCallingClearOnNonEmpty() {
ifSupported(() -> {
final java.util.List<Character> list = of('1');
list.clear();
assertThat(list).isEqualTo(asList());
});
}
// -- contains(Object)
@Test
public void shouldRecognizeThatEmptyListViewDoesNotContainElement() {
assertThat(empty().contains('1')).isFalse();
}
@Test
public void shouldRecognizeThatNonEmptyListViewDoesNotContainElement() {
assertThat(of('1').contains('2')).isFalse();
}
@Test
public void shouldRecognizeThatNWhenEmptyListViewContainElement() {
assertThat(of('1').contains('1')).isTrue();
}
@Test
public void shouldEnsureThatEmptyListViewContainsPermitsNullElements() {
assertThat(empty().contains(null)).isFalse();
}
@Test
public void shouldEnsureThatNonEmptyListViewContainsPermitsNullElements() {
if (elementNullability == NULLABLE) {
assertThat(ofNull().contains(null)).isTrue();
}
}
@Test
public void shouldBehaveLikeStandardJavaWhenCallingContainsOfIncompatibleTypeOnEmpty() {
assertThat(empty().contains("")).isFalse();
}
@Test
public void shouldBehaveLikeStandardJavaWhenCallingContainsOfIncompatibleTypeWhenNotEmpty() {
assertThat(of('1').contains("")).isFalse();
}
@Test
public void shouldRecognizeListContainsSelf() {
if (elementType == GENERIC) {
ifSupported(() -> {
final java.util.List<Object> list = empty();
list.add(list);
assertThat(list.contains(list)).isTrue();
});
}
}
// -- containsAll(Collection)
@Test
public void shouldThrowNPEWhenCallingContainsAllNullWhenEmpty() {
assertThatThrownBy(() -> empty().containsAll(null))
.isInstanceOf(NullPointerException.class);
}
@Test
public void shouldThrowNPEWhenCallingContainsAllNullWhenNotEmpty() {
assertThatThrownBy(() -> of('1').containsAll(null))
.isInstanceOf(NullPointerException.class);
}
@Test
public void shouldRecognizeNonEmptyContainsAllEmpty() {
assertThat(of('1').containsAll(asList())).isTrue();
}
@Test
public void shouldRecognizeNonEmptyContainsAllNonEmpty() {
assertThat(of('1').containsAll(asList('1'))).isTrue();
}
@Test
public void shouldRecognizeNonEmptyNotContainsAllNonEmpty() {
assertThat(of('1', '2').containsAll(asList('1', '3'))).isFalse();
}
@Test
public void shouldRecognizeEmptyContainsAllEmpty() {
assertThat(empty().containsAll(asList())).isTrue();
}
@Test(expected = NullPointerException.class)
public void shouldThrowOnEmptyContainsAllGivenNull() {
empty().containsAll(null);
}
@Test
public void shouldRecognizeListContainsAllSelf() {
if (elementType == GENERIC) {
ifSupported(() -> {
final java.util.List<Object> list = empty();
list.add(list);
assertThat(list.containsAll(list)).isTrue();
});
}
}
// -- equals(Object)
@Test
public void shouldRecognizeEqualsSame() {
final java.util.List<Character> list = of('1');
assertThat(list.equals(list)).isTrue();
}
@Test
public void shouldRecognizeEmptyEqualsEmpty() {
assertThat(empty().equals(empty())).isTrue();
}
@Test
public void shouldRecognizeNonEmptyEqualsNonEmpty() {
assertThat(of('1').equals(of('1'))).isTrue();
}
@Test
public void shouldRecognizeNonEmptyNotEqualsNonEmpty() {
assertThat(of('1', '2').equals(of('1', '3'))).isFalse();
}
@Test
public void shouldRecognizeEmptyNotEqualsNonEmpty() {
assertThat(empty().equals(of('1'))).isFalse();
}
@Test
public void shouldRecognizeNonEmptyNotEqualsEmpty() {
assertThat(of('1').equals(empty())).isFalse();
}
@Test
public void shouldRecognizeEmptyNotEqualsNull() {
assertThat(empty().equals(null)).isFalse();
}
@Test
public void shouldRecognizeNonEmptyNotEqualsNull() {
assertThat(of('1').equals(null)).isFalse();
}
@Test
public void shouldRecognizeNonEqualityOfSameValuesOfDifferentType() {
if (elementType == GENERIC) {
assertThat(of(1).equals(of(1.0d))).isFalse();
}
}
@Test
public void shouldRecognizeSelfEqualityOfListThatContainsItself() {
if (elementType == GENERIC) {
ifSupported(() -> {
final java.util.List<Object> list = empty();
list.add(list);
assertThat(list.equals(list)).isTrue();
});
}
}
// -- get(int)
@Test
public void shouldThrowWhenEmptyGetWithNegativeIndex() {
assertThatThrownBy(() -> empty().get(-1))
.isInstanceOf(IndexOutOfBoundsException.class);
}
@Test
public void shouldThrowWhenEmptyGetWithIndexEqualsSize() {
assertThatThrownBy(() -> empty().get(0))
.isInstanceOf(IndexOutOfBoundsException.class);
}
@Test
public void shouldThrowWhenNonEmptyGetWithNegativeIndex() {
assertThatThrownBy(() -> of('1').get(-1))
.isInstanceOf(IndexOutOfBoundsException.class);
}
@Test
public void shouldThrowWhenNonEmptyGetWithIndexEqualsSize() {
assertThatThrownBy(() -> of('1').get(1))
.isInstanceOf(IndexOutOfBoundsException.class);
}
@Test
public void shouldGetAtFirstIndex() {
assertThat(of('1', '2', '3').get(0)).isEqualTo('1');
}
@Test
public void shouldGetAtLastIndex() {
assertThat(of('1', '2', '3').get(2)).isEqualTo('3');
}
// -- hashCode()
@Test
public void shouldCalculateHashCodeOfEmptyLikeJava() {
assertThat(empty().hashCode()).isEqualTo(asList().hashCode());
}
@Test
public void shouldCalculateHashCodeOfNonEmptyLikeJava() {
assertThat(of('1', '2', '3').hashCode()).isEqualTo(asList('1', '2', '3').hashCode());
}
@Test
public void shouldThrowInsteadOfLoopingInfinitelyWhenComputingHashCodeOfListThatContainsItself() {
if (elementType == GENERIC) {
ifSupported(() -> {
final java.util.List<Object> list = empty();
list.add(list);
list.hashCode();
}, StackOverflowError.class);
}
}
// -- indexOf(Object)
@Test
public void shouldReturnIndexOfNonExistingElementWhenEmpty() {
assertThat(empty().indexOf('0')).isEqualTo(-1);
}
@Test
public void shouldReturnIndexOfNonExistingElementWhenNonEmpty() {
assertThat(of('1', '2', '3').indexOf('0')).isEqualTo(-1);
}
@Test
public void shouldReturnIndexOfFirstOccurrenceWhenNonEmpty() {
assertThat(of('1', '2', '3', '2').indexOf('2')).isEqualTo(1);
}
@Test
public void shouldReturnIndexOfNullWhenNonEmpty() {
if (elementNullability == NULLABLE) {
assertThat(of('1', null, '2', null).indexOf(null)).isEqualTo(1);
}
}
@Test
public void shouldReturnIndexOfWrongTypedElementWhenNonEmpty() {
if (elementType == GENERIC) {
assertThat(of('1', '2').indexOf("a")).isEqualTo(-1);
}
}
// -- isEmpty()
@Test
public void shouldReturnTrueWhenCallingIsEmptyWhenEmpty() {
assertThat(empty().isEmpty()).isTrue();
}
@Test
public void shouldReturnFalseWhenCallingIsEmptyWhenNotEmpty() {
assertThat(of('1').isEmpty()).isFalse();
}
// -- iterator()
@Test
public void shouldReturnIteratorWhenEmpty() {
assertThat(empty().iterator()).isNotNull();
}
@Test
public void shouldReturnIteratorWhenNotEmpty() {
assertThat(of('1').iterator()).isNotNull();
}
@Test
public void shouldReturnEmptyIteratorWhenEmpty() {
assertThat(empty().iterator().hasNext()).isFalse();
}
@Test
public void shouldReturnNonEmptyIteratorWhenNotEmpty() {
assertThat(of('1').iterator().hasNext()).isTrue();
}
@Test
public void shouldThrowWhenCallingNextOnIteratorWhenEmpty() {
assertThatThrownBy(() -> empty().iterator().next())
.isInstanceOf(NoSuchElementException.class);
}
@Test
public void shouldNotThrowWhenCallingNextOnIteratorWhenNotEmpty() {
assertThat(of('1').iterator().next()).isEqualTo('1');
}
@Test
public void shouldThrowWhenCallingNextTooOftenOnIteratorWhenNotEmpty() {
final java.util.Iterator<Character> iterator = of('1').iterator();
iterator.next();
assertThatThrownBy(iterator::next).isInstanceOf(NoSuchElementException.class);
}
@Test
public void shouldIterateAsExpectedWhenCallingIteratorWhenNotEmpty() {
final java.util.Iterator<Character> iterator = of('1', '2', '3').iterator();
assertThat(iterator.next()).isEqualTo('1');
assertThat(iterator.next()).isEqualTo('2');
assertThat(iterator.next()).isEqualTo('3');
}
@Test
public void shouldNotHaveNextWhenAllIteratorElementsWereConsumedByNext() {
final java.util.Iterator<Character> iterator = of('1').iterator();
iterator.next();
assertThat(iterator.hasNext()).isFalse();
}
// -- iterator().forEachRemaining()
@Test
public void shouldPerformNoSideEffectForEachRemainingOfEmpty() {
final java.util.List<Character> actual = new java.util.ArrayList<>();
this.<Character> empty().<Character> iterator().forEachRemaining(actual::add);
assertThat(actual.isEmpty()).isTrue();
}
@Test
public void shouldPerformNoSideEffectsForEachRemainingOfNonEmptyButAllIterated() {
final java.util.List<Character> actual = new java.util.ArrayList<>();
final java.util.Iterator<Character> iterator = of('1').iterator();
iterator.next();
iterator.forEachRemaining(actual::add);
assertThat(actual.isEmpty()).isTrue();
}
@Test
public void shouldPerformSideEffectsForEachRemainingOfNonEmpty() {
final java.util.List<Character> actual = new java.util.ArrayList<>();
final java.util.Iterator<Character> iterator = of('1', '2').iterator();
iterator.next();
iterator.forEachRemaining(actual::add);
assertThat(actual).isEqualTo(asList('2'));
}
@Test
public void shouldThrowWhenRemovingElementFromListWhileIteratingForEachRemaining() {
ifSupported(() -> {
final java.util.List<Character> list = of('1');
final java.util.Iterator<Character> iterator = list.iterator();
iterator.forEachRemaining(list::remove);
}, ConcurrentModificationException.class);
}
@Test
public void shouldThrowWhenAddingElementFromListWhileIteratingForEachRemaining() {
ifSupported(() -> {
final java.util.List<Character> list = of('1');
final java.util.Iterator<Character> iterator = list.iterator();
iterator.forEachRemaining(list::add);
}, ConcurrentModificationException.class);
}
@Test
public void shouldThrowWhenRemovingElementFromIteratorWhileIteratingForEachRemaining() {
ifSupported(() -> {
final java.util.Iterator<Character> iterator = of('1', '2').iterator();
iterator.forEachRemaining(e -> iterator.remove());
}, IllegalStateException.class);
}
// -- iterator().remove()
@Test
public void shouldThrowWhenCallingRemoveOnEmptyIterator() {
ifSupported(() -> empty().iterator().remove(), IllegalStateException.class);
}
@Test
public void shouldThrowWhenCallingRemoveOnNonEmptyIteratorWithoutHavingCalledNext() {
ifSupported(() -> of('1').iterator().remove(), IllegalStateException.class);
}
@Test
public void shouldThrowWhenCallingRemoveTwiceOnNonEmptyIteratorAfterHavingCalledNext() {
ifSupported(() -> {
final java.util.Iterator<Character> iter = of('1', '2', '3').iterator();
iter.next();
iter.remove();
iter.remove(); // should fail
}, IllegalStateException.class);
}
@Test
public void shouldThrowWhenModifyingListWhileIteratingAndRemoving() {
ifSupported(() -> {
final java.util.List<Character> list = of('1', '2', '3');
final java.util.Iterator<Character> iter = list.iterator();
iter.next();
list.add('4');
iter.remove();
}, ConcurrentModificationException.class);
}
@Test
public void shouldRemoveFirstListElementWhenIterating() {
ifSupported(() -> {
final java.util.List<Character> list = of('1', '2', '3');
final java.util.Iterator<Character> iter = list.iterator();
iter.next();
iter.remove();
assertThat(list).isEqualTo(asList('2', '3'));
});
}
@Test
public void shouldRemoveInnerListElementWhenIterating() {
ifSupported(() -> {
final java.util.List<Character> list = of('1', '2', '3');
final java.util.Iterator<Character> iter = list.iterator();
iter.next();
iter.next();
iter.remove();
assertThat(list).isEqualTo(asList('1', '3'));
});
}
@Test
public void shouldRemoveLastListElementWhenIterating() {
ifSupported(() -> {
final java.util.List<Character> list = of('1', '2', '3');
final java.util.Iterator<Character> iter = list.iterator();
iter.next();
iter.next();
iter.next();
iter.remove();
assertThat(list).isEqualTo(asList('1', '2'));
});
}
// -- lastIndexOf()
@Test
public void shouldReturnLastIndexOfNonExistingElementWhenEmpty() {
assertThat(empty().lastIndexOf('0')).isEqualTo(-1);
}
@Test
public void shouldReturnLastIndexOfNonExistingElementWhenNonEmpty() {
assertThat(of('1', '2', '3').lastIndexOf('0')).isEqualTo(-1);
}
@Test
public void shouldReturnLastIndexOfFirstOccurrenceWhenNonEmpty() {
assertThat(of('1', '2', '3', '2').lastIndexOf('2')).isEqualTo(3);
}
@Test
public void shouldReturnLastIndexOfNullWhenNonEmpty() {
if (elementNullability == NULLABLE) {
assertThat(of('1', null, '2', null).lastIndexOf(null)).isEqualTo(3);
}
}
@Test
public void shouldReturnLastIndexOfWrongTypedElementWhenNonEmpty() {
if (elementType == GENERIC) {
assertThat(of('1', null, '2').lastIndexOf("a")).isEqualTo(-1);
}
}
// -- listIterator()
@Test
public void shouldReturnListIteratorWhenEmpty() {
assertThat(empty().listIterator()).isNotNull();
}
@Test
public void shouldReturnListIteratorWhenNotEmpty() {
assertThat(of('1').listIterator()).isNotNull();
}
// -- listIterator().add()
@Test
public void shouldUseListIteratorToAddElementToEmptyList() {
ifSupported(() -> {
final java.util.List<Character> list = empty();
list.listIterator().add('1');
assertThat(list).isEqualTo(asList('1'));
});
}
@Test
public void shouldAddElementToListIteratorStart() {
ifSupported(() -> {
final java.util.List<Character> list = of('1');
list.listIterator().add('2');
assertThat(list).isEqualTo(asList('2', '1'));
});
}
@Test
public void shouldAddingElementToListIteratorEnd() {
ifSupported(() -> {
final java.util.List<Character> list = of('1');
final ListIterator<Character> listIterator = list.listIterator();
listIterator.next();
listIterator.add('2');
assertThat(list).isEqualTo(asList('1', '2'));
});
}
@Test
public void shouldAddElementHavingWrongTypeToListIterator() {
if (elementType == GENERIC) {
ifSupported(() -> {
final java.util.List<Character> list = of('1');
@SuppressWarnings("unchecked") final ListIterator<Object> listIterator = (ListIterator<Object>) (Object) list.listIterator();
listIterator.add("x");
assertThat(list).isEqualTo(asList("x", '1'));
});
}
}
@Test
public void shouldReturnUnaffectedNextWhenCallingAddOnListIterator() {
ifSupported(() -> {
final ListIterator<Character> listIterator = of('1').listIterator();
listIterator.add('2');
assertThat(listIterator.next()).isEqualTo('1');
});
}
@Test
public void shouldReturnNewElementWhenCallingAddAndThenPreviousOnListIterator() {
ifSupported(() -> {
final ListIterator<Character> listIterator = of('1').listIterator();
listIterator.next();
listIterator.add('2');
assertThat(listIterator.previous()).isEqualTo('2');
});
}
@Test
public void shouldIncreaseNextIndexByOneWhenCallingAddOnListIterator() {
ifSupported(() -> {
final ListIterator<Character> listIterator = of('1').listIterator();
assertThat(listIterator.nextIndex()).isEqualTo(0);
listIterator.add('2');
assertThat(listIterator.nextIndex()).isEqualTo(1);
});
}
@Test
public void shouldIncreasePreviousIndexByOneWhenCallingAddOnListIterator() {
ifSupported(() -> {
final ListIterator<Character> listIterator = of('1').listIterator();
assertThat(listIterator.previousIndex()).isEqualTo(-1);
listIterator.add('2');
assertThat(listIterator.previousIndex()).isEqualTo(0);
});
}
// -- listIterator().hasNext()
@Test
public void shouldNotHaveNextWhenEmptyListIterator() {
assertThat(empty().listIterator().hasNext()).isFalse();
}
@Test
public void shouldHaveNextWhenNonEmptyListIterator() {
assertThat(of('1').listIterator().hasNext()).isTrue();
}
@Test
public void shouldNotHaveNextWhenAllListIteratorElementsWereConsumedByNext() {
final ListIterator<Character> listIterator = of('1').listIterator();
assertThat(listIterator.hasNext()).isTrue();
listIterator.next();
assertThat(listIterator.hasNext()).isFalse();
}
// -- listIterator().next()
@Test
public void shouldThrowWhenCallingNextOnListIteratorWhenEmpty() {
assertThatThrownBy(() -> empty().listIterator().next())
.isInstanceOf(NoSuchElementException.class);
}
@Test
public void shouldNotThrowWhenCallingNextOnListIteratorWhenNotEmpty() {
assertThat(of('1').listIterator().next()).isEqualTo('1');
}
@Test
public void shouldThrowWhenCallingNextTooOftenOnListIteratorWhenNotEmpty() {
final ListIterator<Character> listIterator = of('1').listIterator();
listIterator.next();
assertThatThrownBy(listIterator::next).isInstanceOf(NoSuchElementException.class);
}
@Test
public void shouldIterateAsExpectedWhenCallingListIteratorWhenNotEmpty() {
final ListIterator<Character> listIterator = of('1', '2', '3').listIterator();
assertThat(listIterator.next()).isEqualTo('1');
assertThat(listIterator.next()).isEqualTo('2');
assertThat(listIterator.next()).isEqualTo('3');
}
@Test
public void shouldThrowWhenCallingListIteratorNextAndListElementWasRemoved() {
ifSupported(() -> {
final java.util.List<Character> list = of('1');
final ListIterator<Character> listIterator = list.listIterator();
assertThat(listIterator.hasNext()).isTrue();
list.remove(0);
listIterator.next();
}, ConcurrentModificationException.class);
}
@Test
public void shouldThrowWhenCallingListIteratorNextAndListElementWasAdded() {
ifSupported(() -> {
final java.util.List<Character> list = of('1');
final ListIterator<Character> listIterator = list.listIterator();
assertThat(listIterator.hasNext()).isTrue();
list.add('2');
listIterator.next();
}, ConcurrentModificationException.class);
}
// -- listIterator().nextIndex()
@Test
public void shouldReturnNextIndexOfEmptyListIterator() {
assertThat(empty().listIterator().nextIndex()).isEqualTo(0);
}
@Test
public void shouldReturnNextIndexOfNonEmptyListIterator() {
assertThat(of('1').listIterator().nextIndex()).isEqualTo(0);
}
@Test
public void shouldReturnCorrectNextIndexOfListIteratorAfterIteratingAllElements() {
final ListIterator<Character> listIterator = of('1').listIterator();
listIterator.next();
assertThat(listIterator.nextIndex()).isEqualTo(1);
}
// -- listIterator().hasPrevious()
@Test
public void shouldNotHavePreviousWhenEmptyListIterator() {
assertThat(empty().listIterator().hasPrevious()).isFalse();
}
@Test
public void shouldNotHavePreviousWhenNonEmptyListIterator() {
assertThat(of('1').listIterator().hasPrevious()).isFalse();
}
@Test
public void shouldNotHavePreviousWhenAllListIteratorElementsWereConsumedByPrevious() {
final ListIterator<Character> listIterator = of('1').listIterator();
listIterator.next();
assertThat(listIterator.hasPrevious()).isTrue();
listIterator.previous();
assertThat(listIterator.hasPrevious()).isFalse();
}
// -- listIterator().previous()
@Test
public void shouldThrowWhenCallingPreviousOnListIteratorWhenEmpty() {
assertThatThrownBy(() -> empty().listIterator().previous())
.isInstanceOf(NoSuchElementException.class);
}
@Test
public void shouldThrowWhenCallingPreviousOnListIteratorWhenNotEmpty() {
assertThatThrownBy(() -> of('1').listIterator().previous())
.isInstanceOf(NoSuchElementException.class);
}
@Test
public void shouldRepeatedlyReturnTheSameElementWhenAlternatingNextAndPrevious() {
final ListIterator<Character> listIterator = of('1').listIterator();
final java.util.List<Character> actual = new java.util.ArrayList<>();
actual.add(listIterator.next());
actual.add(listIterator.previous());
actual.add(listIterator.next());
actual.add(listIterator.previous());
assertThat(actual).isEqualTo(asList('1', '1', '1', '1'));
}
@Test
public void shouldIterateListIteratorBackwards() {
final ListIterator<Character> listIterator = of('1', '2', '3', '4').listIterator();
final java.util.List<Character> actual = new java.util.ArrayList<>();
while (listIterator.hasNext()) {
listIterator.next();
}
while (listIterator.hasPrevious()) {
actual.add(listIterator.previous());
}
assertThat(actual).isEqualTo(asList('4', '3', '2', '1'));
}
@Test
public void shouldThrowWhenCallingPreviousTooOftenOnListIteratorWhenNotEmpty() {
final ListIterator<Character> listIterator = of('1').listIterator();
listIterator.next();
listIterator.previous();
assertThatThrownBy(listIterator::previous).isInstanceOf(NoSuchElementException.class);
}
@Test
public void shouldThrowWhenCallingListIteratorPreviousAndListElementWasRemoved() {
ifSupported(() -> {
final java.util.List<Character> list = of('1');
final ListIterator<Character> listIterator = list.listIterator();
assertThat(listIterator.hasPrevious()).isFalse();
listIterator.next();
assertThat(listIterator.hasPrevious()).isTrue();
list.remove(0);
listIterator.previous();
}, ConcurrentModificationException.class);
}
@Test
public void shouldThrowWhenCallingListIteratorPreviousAndListElementWasAdded() {
ifSupported(() -> {
final java.util.List<Character> list = of('1');
final ListIterator<Character> listIterator = list.listIterator();
assertThat(listIterator.hasPrevious()).isFalse();
listIterator.next();
assertThat(listIterator.hasPrevious()).isTrue();
list.add('2');
listIterator.previous();
}, ConcurrentModificationException.class);
}
// -- listIterator.previousIndex()
@Test
public void shouldReturnPreviousIndexOfEmptyListIterator() {
assertThat(empty().listIterator().previousIndex()).isEqualTo(-1);
}
@Test
public void shouldReturnPreviousIndexOfNonEmptyListIterator() {
assertThat(of('1').listIterator().previousIndex()).isEqualTo(-1);
}
@Test
public void shouldReturnCorrectPreviousIndexOfListIteratorAfterIteratingAllElements() {
final ListIterator<Character> listIterator = of('1').listIterator();
listIterator.next();
assertThat(listIterator.previousIndex()).isEqualTo(0);
}
// -- listIterator().remove()
@Test
public void shouldThrowWhenCallingRemoveOnEmptyListIterator() {
ifSupported(() -> empty().listIterator().remove(), IllegalStateException.class);
}
@Test
public void shouldThrowWhenCallingRemoveOnNonEmptyListIterator() {
ifSupported(() -> of('1').listIterator().remove(), IllegalStateException.class);
}
@Test
public void shouldThrowWhenCallingRemoveAfterRemoveHasBeenCalledAfterTheLastCallOfNext() {
ifSupported(() -> {
final java.util.List<Character> list = of('1', '2', '3');
final ListIterator<Character> listIterator = list.listIterator();
listIterator.next();
listIterator.next();
listIterator.remove();
assertThatThrownBy(listIterator::remove).isInstanceOf(IllegalStateException.class);
});
}
@Test
public void shouldThrowWhenCallingRemoveAfterRemoveHasBeenCalledAfterTheLastCallOfPrevious() {
ifSupported(() -> {
final java.util.List<Character> list = of('1', '2', '3');
final ListIterator<Character> listIterator = list.listIterator();
listIterator.next();
listIterator.next();
listIterator.previous();
listIterator.remove();
assertThatThrownBy(listIterator::remove).isInstanceOf(IllegalStateException.class);
});
}
@Test
public void shouldThrowWhenCallingRemoveAfterAddHasBeenCalledAfterTheLastCallOfNext() {
ifSupported(() -> {
final java.util.List<Character> list = of('1', '2', '3');
final ListIterator<Character> listIterator = list.listIterator();
listIterator.next();
listIterator.add('4');
assertThatThrownBy(listIterator::remove).isInstanceOf(IllegalStateException.class);
});
}
@Test
public void shouldThrowWhenCallingRemoveAfterAddHasBeenCalledAfterTheLastCallOfPrevious() {
ifSupported(() -> {
final java.util.List<Character> list = of('1', '2', '3');
final ListIterator<Character> listIterator = list.listIterator();
listIterator.next();
listIterator.previous();
listIterator.add('4');
assertThatThrownBy(listIterator::remove).isInstanceOf(IllegalStateException.class);
});
}
@Test
public void shouldRemoveLastElementOfListIteratorThatWasReturnedByNext() {
ifSupported(() -> {
final java.util.List<Character> list = of('1', '2', '3');
final ListIterator<Character> listIterator = list.listIterator();
listIterator.next();
assertThat(listIterator.next()).isEqualTo('2');
listIterator.remove();
assertThat(list).isEqualTo(asList('1', '3'));
});
}
@Test
public void shouldRemoveLastElementOfListIteratorThatWasReturnedByPrevious() {
ifSupported(() -> {
final java.util.List<Character> list = of('1', '2', '3');
final ListIterator<Character> listIterator = list.listIterator();
listIterator.next();
listIterator.next();
assertThat(listIterator.previous()).isEqualTo('2');
listIterator.remove();
assertThat(list).isEqualTo(asList('1', '3'));
});
}
@Test
public void shouldThrowWhenCallingRemoveOnListIteratorAfterListWasChanged() {
ifSupported(() -> {
final java.util.List<Character> list = of('1');
final ListIterator<Character> listIterator = list.listIterator();
listIterator.next();
list.add('2');
assertThatThrownBy(listIterator::remove).isInstanceOf(ConcurrentModificationException.class);
});
}
// -- listIterator().set()
@Test
public void shouldThrowWhenCallingSetOnEmptyListIterator() {
ifSupported(() -> empty().listIterator().set('0'), IllegalStateException.class);
}
@Test
public void shouldThrowWhenCallingSetOnNonEmptyListIterator() {
ifSupported(() -> of('1').listIterator().set('0'), IllegalStateException.class);
}
@Test
public void shouldThrowWhenCallingSetAfterRemoveHasBeenCalledAfterTheLastCallOfNext() {
ifSupported(() -> {
final java.util.List<Character> list = of('1', '2', '3');
final ListIterator<Character> listIterator = list.listIterator();
listIterator.next();
listIterator.next();
listIterator.remove();
assertThatThrownBy(() -> listIterator.set('0')).isInstanceOf(IllegalStateException.class);
});
}
@Test
public void shouldThrowWhenCallingSetAfterRemoveHasBeenCalledAfterTheLastCallOfPrevious() {
ifSupported(() -> {
final java.util.List<Character> list = of('1', '2', '3');
final ListIterator<Character> listIterator = list.listIterator();
listIterator.next();
listIterator.next();
listIterator.previous();
listIterator.remove();
assertThatThrownBy(() -> listIterator.set('0')).isInstanceOf(IllegalStateException.class);
});
}
@Test
public void shouldThrowWhenCallingSetAfterAddHasBeenCalledAfterTheLastCallOfNext() {
ifSupported(() -> {
final java.util.List<Character> list = of('1', '2', '3');
final ListIterator<Character> listIterator = list.listIterator();
listIterator.next();
listIterator.add('4');
assertThatThrownBy(() -> listIterator.set('0')).isInstanceOf(IllegalStateException.class);
});
}
@Test
public void shouldThrowWhenCallingSetAfterAddHasBeenCalledAfterTheLastCallOfPrevious() {
ifSupported(() -> {
final java.util.List<Character> list = of('1', '2', '3');
final ListIterator<Character> listIterator = list.listIterator();
listIterator.next();
listIterator.previous();
listIterator.add('4');
assertThatThrownBy(() -> listIterator.set('0')).isInstanceOf(IllegalStateException.class);
});
}
@Test
public void shouldSetLastElementOfListIteratorThatWasReturnedByNext() {
ifSupported(() -> {
final java.util.List<Character> list = of('1', '2', '3');
final ListIterator<Character> listIterator = list.listIterator();
listIterator.next();
assertThat(listIterator.next()).isEqualTo('2');
listIterator.set('0');
assertThat(list).isEqualTo(asList('1', '0', '3'));
});
}
@Test
public void shouldSetLastElementOfListIteratorThatWasReturnedByPrevious() {
ifSupported(() -> {
final java.util.List<Character> list = of('1', '2', '3');
final ListIterator<Character> listIterator = list.listIterator();
listIterator.next();
listIterator.next();
assertThat(listIterator.previous()).isEqualTo('2');
listIterator.set('0');
assertThat(list).isEqualTo(asList('1', '0', '3'));
});
}
@Test
public void shouldThrowWhenCallingSetOnListIteratorAfterListWasChanged() {
ifSupported(() -> {
final java.util.List<Character> list = of('1');
final ListIterator<Character> listIterator = list.listIterator();
listIterator.next();
list.add('2');
assertThatThrownBy(() -> listIterator.set('0')).isInstanceOf(ConcurrentModificationException.class);
});
}
// -- listIterator(int)
@Test
public void shouldThrowWhenListIteratorAtNegativeIndexWhenEmpty() {
assertThatThrownBy(() -> empty().listIterator(-1))
.isInstanceOf(IndexOutOfBoundsException.class);
}
@Test
public void shouldThrowWhenListIteratorAtNegativeIndexWhenNotEmpty() {
assertThatThrownBy(() -> of('1').listIterator(-1))
.isInstanceOf(IndexOutOfBoundsException.class);
}
@Test
public void shouldNotThrowWhenListIteratorAtSizeIndexWhenEmpty() {
assertThat(empty().listIterator(0)).isNotNull();
}
@Test
public void shouldNotThrowWhenListIteratorAtSizeIndexWhenNotEmpty() {
assertThat(of('1').listIterator(1)).isNotNull();
}
@Test
public void shouldThrowWhenListIteratorAtIndexGreaterSizeWhenEmpty() {
assertThatThrownBy(() -> empty().listIterator(1))
.isInstanceOf(IndexOutOfBoundsException.class);
}
@Test
public void shouldThrowWhenListIteratorAtIndexGreaterSizeWhenNotEmpty() {
assertThatThrownBy(() -> of('1').listIterator(2))
.isInstanceOf(IndexOutOfBoundsException.class);
}
// -- listIterator(int).hasNext()
@Test
public void shouldReturnEmptyListIteratorAtFirstIndexWhenEmpty() {
assertThat(empty().listIterator(0).hasNext()).isFalse();
}
@Test
public void shouldReturnNonEmptyListIteratorAtFirstIndexWhenNotEmpty() {
assertThat(of('1').listIterator(0).hasNext()).isTrue();
}
@Test
public void shouldNotHaveNextWhenAllListIteratorElementsAtFirstIndexWereConsumedByNext() {
final ListIterator<Character> listIterator = of('1').listIterator(0);
listIterator.next();
assertThat(listIterator.hasNext()).isFalse();
}
// -- listIterator(int).next()
@Test
public void shouldThrowWhenCallingNextOnListIteratorAtFirstIndexWhenEmpty() {
assertThatThrownBy(() -> empty().listIterator(0).next())
.isInstanceOf(NoSuchElementException.class);
}
@Test
public void shouldNotThrowWhenCallingNextOnListIteratorAtFirstIndexWhenNotEmpty() {
assertThat(of('1').listIterator(0).next()).isEqualTo('1');
}
@Test
public void shouldThrowWhenCallingNextTooOftenOnListIteratorAtFirstIndexWhenNotEmpty() {
final java.util.Iterator<Character> listIterator = of('1').listIterator(0);
listIterator.next();
assertThatThrownBy(listIterator::next).isInstanceOf(NoSuchElementException.class);
}
@Test
public void shouldIterateAsExpectedWhenCallingListIteratorAtFirstIndexWhenNotEmpty() {
final ListIterator<Character> listIterator = of('1', '2', '3').listIterator(0);
assertThat(listIterator.next()).isEqualTo('1');
assertThat(listIterator.next()).isEqualTo('2');
assertThat(listIterator.next()).isEqualTo('3');
}
@Test
public void shouldIterateAsExpectedWhenCallingListIteratorAtNonFirstIndexWhenNotEmpty() {
final ListIterator<Character> listIterator = of('1', '2', '3').listIterator(1);
assertThat(listIterator.next()).isEqualTo('2');
assertThat(listIterator.next()).isEqualTo('3');
}
// -- listIterator().nextIndex()
@Test
public void shouldReturnNextIndexOfEmptyListIteratorAtFirstIndex() {
assertThat(empty().listIterator(0).nextIndex()).isEqualTo(0);
}
@Test
public void shouldReturnNextIndexOfNonEmptyListIteratorAtIndex1() {
assertThat(of('1').listIterator(1).nextIndex()).isEqualTo(1);
}
@Test
public void shouldReturnCorrectNextIndexOfListIteratorAtIndex1AfterIteratingAllElements() {
final ListIterator<Character> listIterator = of('1', '2').listIterator(1);
listIterator.next();
assertThat(listIterator.nextIndex()).isEqualTo(2);
}
// -- listIterator().hasPrevious()
@Test
public void shouldNotHavePreviousWhenEmptyListIteratorAtIndex0() {
assertThat(empty().listIterator(0).hasPrevious()).isFalse();
}
@Test
public void shouldHavePreviousWhenNonEmptyListIteratorAtIndex1() {
assertThat(of('1').listIterator(1).hasPrevious()).isTrue();
}
@Test
public void shouldNotHavePreviousWhenAllListIteratorAtIndex0ElementsWereConsumedByPrevious() {
final ListIterator<Character> listIterator = of('1').listIterator(1);
assertThat(listIterator.hasPrevious()).isTrue();
listIterator.previous();
assertThat(listIterator.hasPrevious()).isFalse();
}
// -- listIterator().previous()
@Test
public void shouldThrowWhenCallingPreviousOnListIteratorAtIndex0WhenEmpty() {
assertThatThrownBy(() -> empty().listIterator(0).previous())
.isInstanceOf(NoSuchElementException.class);
}
@Test
public void shouldThrowWhenCallingPreviousOnListIteratorAtIndex0WhenNotEmpty() {
assertThatThrownBy(() -> of('1').listIterator(0).previous())
.isInstanceOf(NoSuchElementException.class);
}
@Test
public void shouldRepeatedlyReturnTheSameElementWhenAlternatingNextAndPreviousAtIndex1() {
final ListIterator<Character> listIterator = of('1').listIterator(1);
final java.util.List<Character> actual = new java.util.ArrayList<>();
actual.add(listIterator.previous());
actual.add(listIterator.next());
actual.add(listIterator.previous());
actual.add(listIterator.next());
assertThat(actual).isEqualTo(asList('1', '1', '1', '1'));
}
@Test
public void shouldIterateListIteratorAtLastIndexBackwards() {
final ListIterator<Character> listIterator = of('1', '2', '3', '4').listIterator(4);
final java.util.List<Character> actual = new java.util.ArrayList<>();
while (listIterator.hasPrevious()) {
actual.add(listIterator.previous());
}
assertThat(actual).isEqualTo(asList('4', '3', '2', '1'));
}
@Test
public void shouldThrowWhenCallingPreviousTooOftenOnListIteratorAtIndex1WhenNotEmpty() {
final ListIterator<Character> listIterator = of('1').listIterator(1);
listIterator.previous();
assertThatThrownBy(listIterator::previous).isInstanceOf(NoSuchElementException.class);
}
@Test
public void shouldThrowWhenCallingListIteratorAtIndex1PreviousAndListElementWasRemoved() {
ifSupported(() -> {
final java.util.List<Character> list = of('1');
final ListIterator<Character> listIterator = list.listIterator(1);
assertThat(listIterator.hasPrevious()).isTrue();
list.remove(0);
listIterator.previous();
}, ConcurrentModificationException.class);
}
@Test
public void shouldThrowWhenCallingListIteratorAtIndex1PreviousAndListElementWasAdded() {
ifSupported(() -> {
final java.util.List<Character> list = of('1');
final ListIterator<Character> listIterator = list.listIterator(1);
assertThat(listIterator.hasPrevious()).isTrue();
list.add('2');
listIterator.previous();
}, ConcurrentModificationException.class);
}
// -- listIterator.previousIndex()
@Test
public void shouldReturnPreviousIndexOfEmptyListIteratorAtIndex0() {
assertThat(empty().listIterator(0).previousIndex()).isEqualTo(-1);
}
@Test
public void shouldReturnPreviousIndexOfNonEmptyListIteratorAtIndex1() {
assertThat(of('1').listIterator(1).previousIndex()).isEqualTo(0);
}
@Test
public void shouldReturnCorrectPreviousIndexOfListIteratorAtIndex1AfterIteratingAllElements() {
final ListIterator<Character> listIterator = of('1', '2').listIterator(1);
listIterator.next();
assertThat(listIterator.previousIndex()).isEqualTo(1);
}
// -- listIterator().remove()
@Test
public void shouldThrowWhenCallingRemoveOnEmptyListIteratorAtIndex0() {
ifSupported(() -> empty().listIterator(0).remove(), IllegalStateException.class);
}
@Test
public void shouldThrowWhenCallingRemoveOnNonEmptyListIteratorAtIndex1() {
ifSupported(() -> of('1').listIterator(1).remove(), IllegalStateException.class);
}
@Test
public void shouldThrowWhenCallingRemoveAfterRemoveHasBeenCalledAfterTheLastCallOfNextAtIndex1() {
ifSupported(() -> {
final java.util.List<Character> list = of('1', '2', '3');
final ListIterator<Character> listIterator = list.listIterator(1);
listIterator.next();
listIterator.remove();
assertThatThrownBy(listIterator::remove).isInstanceOf(IllegalStateException.class);
});
}
@Test
public void shouldThrowWhenCallingRemoveAfterRemoveHasBeenCalledAfterTheLastCallOfPreviousAtIndex1() {
ifSupported(() -> {
final java.util.List<Character> list = of('1', '2', '3');
final ListIterator<Character> listIterator = list.listIterator(1);
listIterator.next();
listIterator.previous();
listIterator.remove();
assertThatThrownBy(listIterator::remove).isInstanceOf(IllegalStateException.class);
});
}
@Test
public void shouldThrowWhenCallingRemoveAfterAddHasBeenCalledAfterTheLastCallOfNextAtIndex1() {
ifSupported(() -> {
final java.util.List<Character> list = of('1', '2', '3');
final ListIterator<Character> listIterator = list.listIterator(1);
listIterator.add('4');
assertThatThrownBy(listIterator::remove).isInstanceOf(IllegalStateException.class);
});
}
@Test
public void shouldThrowWhenCallingRemoveAfterAddHasBeenCalledAfterTheLastCallOfPreviousAtIndex1() {
ifSupported(() -> {
final java.util.List<Character> list = of('1', '2', '3');
final ListIterator<Character> listIterator = list.listIterator(1);
listIterator.previous();
listIterator.add('4');
assertThatThrownBy(listIterator::remove).isInstanceOf(IllegalStateException.class);
});
}
@Test
public void shouldRemoveLastElementOfListIteratorAtIndex1ThatWasReturnedByNext() {
ifSupported(() -> {
final java.util.List<Character> list = of('1', '2', '3');
final ListIterator<Character> listIterator = list.listIterator(1);
assertThat(listIterator.next()).isEqualTo('2');
listIterator.remove();
assertThat(list).isEqualTo(asList('1', '3'));
});
}
@Test
public void shouldRemoveLastElementOfListIteratorAtIndex1ThatWasReturnedByPrevious() {
ifSupported(() -> {
final java.util.List<Character> list = of('1', '2', '3');
final ListIterator<Character> listIterator = list.listIterator(1);
listIterator.next();
assertThat(listIterator.previous()).isEqualTo('2');
listIterator.remove();
assertThat(list).isEqualTo(asList('1', '3'));
});
}
@Test
public void shouldThrowWhenCallingRemoveOnListIteratorAtIndex1AfterListWasChanged() {
ifSupported(() -> {
final java.util.List<Character> list = of('1', '2');
final ListIterator<Character> listIterator = list.listIterator(1);
listIterator.next();
list.add('2');
assertThatThrownBy(listIterator::remove).isInstanceOf(ConcurrentModificationException.class);
});
}
// -- listIterator().set()
@Test
public void shouldThrowWhenCallingSetOnEmptyListIteratorAtIndex0() {
ifSupported(() -> empty().listIterator(0).set('0'), IllegalStateException.class);
}
@Test
public void shouldThrowWhenCallingSetOnNonEmptyListIteratorAtIndex1() {
ifSupported(() -> of('1', '2').listIterator(1).set('0'), IllegalStateException.class);
}
@Test
public void shouldThrowWhenCallingSetAfterRemoveHasBeenCalledAfterTheLastCallOfNextAtIndex1() {
ifSupported(() -> {
final java.util.List<Character> list = of('1', '2', '3');
final ListIterator<Character> listIterator = list.listIterator(1);
listIterator.next();
listIterator.remove();
assertThatThrownBy(() -> listIterator.set('0')).isInstanceOf(IllegalStateException.class);
});
}
@Test
public void shouldThrowWhenCallingSetAfterRemoveHasBeenCalledAfterTheLastCallOfPreviousAtIndex1() {
ifSupported(() -> {
final java.util.List<Character> list = of('1', '2', '3');
final ListIterator<Character> listIterator = list.listIterator(1);
listIterator.next();
listIterator.previous();
listIterator.remove();
assertThatThrownBy(() -> listIterator.set('0')).isInstanceOf(IllegalStateException.class);
});
}
@Test
public void shouldThrowWhenCallingSetAfterAddHasBeenCalledAfterTheLastCallOfNextAtIndex1() {
ifSupported(() -> {
final java.util.List<Character> list = of('1', '2', '3');
final ListIterator<Character> listIterator = list.listIterator(1);
listIterator.next();
listIterator.add('4');
assertThatThrownBy(() -> listIterator.set('0')).isInstanceOf(IllegalStateException.class);
});
}
@Test
public void shouldThrowWhenCallingSetAfterAddHasBeenCalledAfterTheLastCallOfPreviousAtIndex1() {
ifSupported(() -> {
final java.util.List<Character> list = of('1', '2', '3');
final ListIterator<Character> listIterator = list.listIterator(1);
listIterator.next();
listIterator.previous();
listIterator.add('4');
assertThatThrownBy(() -> listIterator.set('0')).isInstanceOf(IllegalStateException.class);
});
}
@Test
public void shouldSetLastElementOfListIteratorAtIndex1ThatWasReturnedByNext() {
ifSupported(() -> {
final java.util.List<Character> list = of('1', '2', '3');
final ListIterator<Character> listIterator = list.listIterator(1);
listIterator.next();
assertThat(listIterator.next()).isEqualTo('3');
listIterator.set('0');
assertThat(list).isEqualTo(asList('1', '2', '0'));
});
}
@Test
public void shouldSetLastElementOfListIteratorAtIndex1ThatWasReturnedByPrevious() {
ifSupported(() -> {
final java.util.List<Character> list = of('1', '2', '3');
final ListIterator<Character> listIterator = list.listIterator(1);
listIterator.next();
assertThat(listIterator.previous()).isEqualTo('2');
listIterator.set('0');
assertThat(list).isEqualTo(asList('1', '0', '3'));
});
}
@Test
public void shouldThrowWhenCallingSetOnListIteratorAtIndex1AfterListWasChanged() {
ifSupported(() -> {
final java.util.List<Character> list = of('1', '2');
final ListIterator<Character> listIterator = list.listIterator(1);
listIterator.next();
list.add('3');
assertThatThrownBy(() -> listIterator.set('0')).isInstanceOf(ConcurrentModificationException.class);
});
}
// -- remove(int)
@Test
public void shouldThrowWhenRemovingElementAtNegativeIndexWhenEmpty() {
ifSupported(() -> empty().remove(-1), IndexOutOfBoundsException.class);
}
@Test
public void shouldThrowWhenRemovingElementAtNegativeIndexWhenNotEmpty() {
ifSupported(() -> of('1').remove(-1), IndexOutOfBoundsException.class);
}
@Test
public void shouldThrowWhenRemovingElementAtSizeIndexWhenEmpty() {
ifSupported(() -> empty().remove(0), IndexOutOfBoundsException.class);
}
@Test
public void shouldThrowWhenRemovingElementAtSizeIndexWhenNotEmpty() {
ifSupported(() -> of('1').remove(1), IndexOutOfBoundsException.class);
}
@Test
public void shouldRemoveTheElementAtFirstIndex() {
ifSupported(() -> {
final java.util.List<Character> list = of('1', '2', '3');
assertThat(list.remove(0)).isEqualTo('1');
assertThat(list).isEqualTo(asList('2', '3'));
});
}
@Test
public void shouldRemoveTheElementAtInnerIndex() {
ifSupported(() -> {
final java.util.List<Character> list = of('1', '2', '3');
assertThat(list.remove(1)).isEqualTo('2');
assertThat(list).isEqualTo(asList('1', '3'));
});
}
@Test
public void shouldRemoveTheElementAtLastIndex() {
ifSupported(() -> {
final java.util.List<Character> list = of('1', '2', '3');
assertThat(list.remove(2)).isEqualTo('3');
assertThat(list).isEqualTo(asList('1', '2'));
});
}
@Test
public void shouldRemoveAllUsingFirstIndex() {
ifSupported(() -> {
final java.util.List<Character> list = of('1', '2', '3');
list.remove(0);
list.remove(0);
list.remove(0);
assertThat(list).isEmpty();
});
}
@Test
public void shouldRemoveAllUsingDescendingIndices() {
ifSupported(() -> {
final java.util.List<Character> list = of('1', '2', '3');
list.remove(2);
list.remove(1);
list.remove(0);
assertThat(list).isEmpty();
});
}
@Test
public void shouldThrowWhenTryingToRemoveMoreElementsThanPresent() {
ifSupported(() -> {
final java.util.List<Character> list = of('1', '2');
list.remove(0);
list.remove(0);
assertThatThrownBy(() -> list.remove(0)).isInstanceOf(IndexOutOfBoundsException.class);
});
}
// -- remove(Object)
@Test
public void shouldRemoveElementFromEmpty() {
ifSupported(() -> {
final java.util.List<Character> list = empty();
assertThat(list.remove((Object) '1')).isFalse();
assertThat(list).isEqualTo(empty());
});
}
@Test
public void shouldRemoveNonExistingElementFromNonEmpty() {
ifSupported(() -> {
final java.util.List<Character> list = of('1', '2');
assertThat(list.remove((Object) '3')).isFalse();
assertThat(list).isEqualTo(of('1', '2'));
});
}
@Test
public void shouldRemoveExistingElementFromNonEmpty() {
ifSupported(() -> {
final java.util.List<Character> list = of('1', '2', '3');
assertThat(list.remove((Object) '2')).isTrue();
assertThat(list).isEqualTo(of('1', '3'));
});
}
@Test
public void shouldRemoveNull() {
if (elementNullability == NULLABLE) {
ifSupported(() -> {
final java.util.List<Character> list = of('1', null, '2');
assertThat(list.remove(null)).isTrue();
assertThat(list).isEqualTo(of('1', '2'));
});
}
}
// -- removeAll(Collection)
@Test
public void shouldThrowNPEWhenCallingRemoveAllNullWhenEmpty() {
assertThatThrownBy(() -> empty().removeAll(null))
.isInstanceOf(NullPointerException.class);
}
@Test
public void shouldThrowNPEWhenCallingRemoveAllNullWhenNotEmpty() {
assertThatThrownBy(() -> of('1').removeAll(null))
.isInstanceOf(NullPointerException.class);
}
@Test
public void shouldRemoveAllWhenCollectionsAreDistinct() {
ifSupported(() -> {
final java.util.List<Character> list = of('1');
assertThat(list.removeAll(asList('2'))).isFalse();
});
}
@Test
public void shouldRemoveAllWhenCollectionsAreNotDistinct() {
ifSupported(() -> {
final java.util.List<Character> list = of('1', '2');
assertThat(list.removeAll(asList('2', '3'))).isTrue();
assertThat(list).isEqualTo(asList('1'));
});
}
@Test
public void shouldRemoveAllWhenCollectionsAreEqual() {
ifSupported(() -> {
final java.util.List<Character> list = of('1', '2');
assertThat(list.removeAll(asList('1', '2'))).isTrue();
assertThat(list).isEmpty();
});
}
@Test
public void shouldRemoveAllEmptyFromEmpty() {
ifSupported(() -> {
final java.util.List<Character> list = of();
assertThat(list.removeAll(asList())).isFalse();
assertThat(list).isEmpty();
});
}
@Test
public void shouldRemoveAllEmptyFromNonEmpty() {
ifSupported(() -> {
final java.util.List<Character> list = of('1');
assertThat(list.removeAll(asList())).isFalse();
assertThat(list).isEqualTo(asList('1'));
});
}
@Test
public void shouldRemoveAllNonEmptyFromEmpty() {
ifSupported(() -> {
final java.util.List<Character> list = empty();
assertThat(list.removeAll(asList('1'))).isFalse();
assertThat(list).isEmpty();
});
}
// -- replaceAll(UnaryOperator)
@Test
public void shouldThrowWhenEmptyReplaceAllGivenNullUnaryOperator() {
assertThatThrownBy(() -> this.<Character> empty().replaceAll(null)).isInstanceOf(NullPointerException.class);
}
@Test
public void shouldThrowWhenNonEmptyReplaceAllGivenNullUnaryOperator() {
assertThatThrownBy(() ->of('1').replaceAll(null)).isInstanceOf(NullPointerException.class);
}
@Test
public void shouldNotThrowWhenReplacingAllOfEmpty() {
empty().replaceAll(UnaryOperator.identity());
}
@Test
public void shouldReplaceAllOfNonEmpty() {
ifSupported(() -> {
final java.util.List<Character> list = of('1', '2');
list.replaceAll(c -> (char) (c + 1));
assertThat(list).isEqualTo(asList('2', '3'));
});
}
// -- retainAll(Collection)
@Test
public void shouldThrowNPEWhenCallingRetainAllNullWhenEmpty() {
assertThatThrownBy(() -> empty().retainAll(null))
.isInstanceOf(NullPointerException.class);
}
@Test
public void shouldThrowNPEWhenCallingRetainAllNullWhenNotEmpty() {
assertThatThrownBy(() -> of('1').retainAll(null))
.isInstanceOf(NullPointerException.class);
}
// -- retainAll(Collection) tests
@Test
public void shouldThrowWhenRetainAllNull() {
assertThatThrownBy(() -> empty().retainAll(null)).isInstanceOf(NullPointerException.class);
assertThatThrownBy(() -> of('1').retainAll(null)).isInstanceOf(NullPointerException.class);
}
@Test
public void shouldRetainAllEmptyOfEmpty() {
ifSupported(() -> {
final java.util.List<Character> list = empty();
assertThat(list.retainAll(asList())).isFalse();
assertThat(list).isEmpty();
});
}
@Test
public void shouldRetainAllEmptyOfNonEmpty() {
ifSupported(() -> {
final java.util.List<Character> list = of('1');
assertThat(list.retainAll(asList())).isTrue();
assertThat(list).isEqualTo(asList());
});
}
@Test
public void shouldRetainAllNonEmptyOfEmpty() {
ifSupported(() -> {
final java.util.List<Character> list = empty();
assertThat(list.retainAll(asList('1'))).isFalse();
assertThat(list).isEqualTo(asList());
});
}
@Test
public void shouldRetainAllWhenDisjoint() {
ifSupported(() -> {
final java.util.List<Character> list = of('1');
assertThat(list.retainAll(asList('2'))).isTrue();
assertThat(list).isEqualTo(asList());
});
}
@Test
public void shouldRetainAllWhenIntersecting() {
ifSupported(() -> {
final java.util.List<Character> list = of('1', '2');
assertThat(list.retainAll(asList('2', '3'))).isTrue();
assertThat(list).isEqualTo(asList('2'));
});
}
@Test
public void shouldRetainAllWhenEqual() {
ifSupported(() -> {
final java.util.List<Character> list = of('1', '2');
assertThat(list.retainAll(asList('1', '2'))).isFalse();
assertThat(list).isEqualTo(asList('1', '2'));
});
}
// -- set(int, T)
@Test
public void shouldThrowWhenSettingElementAtNegativeIndexWhenEmpty() {
ifSupported(() -> empty().set(-1, null), IndexOutOfBoundsException.class);
}
@Test
public void shouldThrowWhenSettingElementAtNegativeIndexWhenNotEmpty() {
ifSupported(() -> of('1').set(-1, null), IndexOutOfBoundsException.class);
}
@Test
public void shouldThrowWhenSettingElementAtSizeIndexWhenEmpty() {
ifSupported(() -> empty().set(0, null), IndexOutOfBoundsException.class);
}
@Test
public void shouldThrowWhenSettingElementAtSizeIndexWhenNotEmpty() {
ifSupported(() -> of('1').set(1, null), IndexOutOfBoundsException.class);
}
@Test
public void shouldSetElementAtFirstIndexWhenListWithSingleElement() {
ifSupported(() -> {
final java.util.List<Character> list = of('1');
assertThat(list.set(0, 'a')).isEqualTo('1');
assertThat(list).isEqualTo(asList('a'));
});
}
@Test
public void shouldSetElementAtFirstIndexWhenListWithThreeElements() {
ifSupported(() -> {
final java.util.List<Character> list = of('1', '2', '3');
assertThat(list.set(0, 'a')).isEqualTo('1');
assertThat(list).isEqualTo(asList('a', '2', '3'));
});
}
@Test
public void shouldSetElementAtLastIndexWhenListWithThreeElements() {
ifSupported(() -> {
final java.util.List<Character> list = of('1', '2', '3');
assertThat(list.set(2, 'a')).isEqualTo('3');
assertThat(list).isEqualTo(asList('1', '2', 'a'));
});
}
@Test
public void shouldSetElementAtMiddleIndexWhenListWithThreeElements() {
ifSupported(() -> {
final java.util.List<Character> list = of('1', '2', '3');
assertThat(list.set(1, 'a')).isEqualTo('2');
assertThat(list).isEqualTo(asList('1', 'a', '3'));
});
}
// -- size()
@Test
public void shouldReturnSizeOfEmpty() {
assertThat(empty().size()).isEqualTo(0);
}
@Test
public void shouldReturnSizeOfNonEmpty() {
assertThat(of('1', '2', '3').size()).isEqualTo(3);
}
// -- sort(Comparator)
@Test
public void shouldSortEmptyList() {
final java.util.List<Character> list = empty();
list.sort(Comparator.naturalOrder());
assertThat(list).isEmpty();
}
@Test
public void shouldSortNonEmptyList() {
ifSupported(() -> {
final java.util.List<Character> list = of('3', '1', '2');
list.sort(Comparator.naturalOrder());
assertThat(list).isEqualTo(asList('1', '2', '3'));
});
}
// -- spliterator()
@Test
public void shouldReturnNonNullSpliteratorWhenEmpty() {
final Spliterator<Object> spliterator = empty().spliterator();
assertThat(spliterator).isNotNull();
assertThat(spliterator.tryAdvance(e -> {
throw new AssertionError("spliterator reports element for empty collection: " + e);
})).isFalse();
}
@Test
public void shouldReturnNonNullSpliteratorWhenNotEmpty() {
final Spliterator<Character> spliterator = of('1').spliterator();
assertThat(spliterator).isNotNull();
assertThat(spliterator.tryAdvance(e -> assertThat(e).isEqualTo('1'))).isTrue();
assertThat(spliterator.tryAdvance(e -> {
throw new AssertionError("spliterator reports element for empty collection: " + e);
})).isFalse();
}
@Test
public void shouldHaveSpliteratorOrderedCharacteristicsWhenEmpty() {
final Spliterator<Object> spliterator = empty().spliterator();
assertThat(spliterator.characteristics() & Spliterator.ORDERED).isEqualTo(Spliterator.ORDERED);
}
@Test
public void shouldHaveSpliteratorOrderedCharacteristicsWhenNotEmpty() {
final Spliterator<Character> spliterator = of('1').spliterator();
assertThat(spliterator.characteristics() & Spliterator.ORDERED).isEqualTo(Spliterator.ORDERED);
}
// -- subList(int, int)
@Test
public void shouldReturnEmptyWhenSubListFrom0To0OnEmpty() {
assertThat(empty().subList(0, 0)).isEmpty();
}
@Test
public void shouldReturnEmptyWhenSubListFrom0To0OnNonEmpty() {
assertThat(of('1').subList(0, 0)).isEmpty();
}
@Test
public void shouldReturnListWithFirstElementWhenSubListFrom0To1OnNonEmpty() {
assertThat(of('1').subList(0, 1)).isEqualTo(asList('1'));
}
@Test
public void shouldReturnEmptyWhenSubListFrom1To1OnNonEmpty() {
assertThat(of('1').subList(1, 1)).isEmpty();
}
@Test
public void shouldReturnSubListWhenIndicesAreWithinRange() {
assertThat(of('1', '2', '3').subList(1, 3)).isEqualTo(asList('2', '3'));
}
@Test
public void shouldReturnEmptyWhenSubListIndicesBothAreUpperBound() {
assertThat(of('1', '2', '3').subList(3, 3)).isEmpty();
}
@Test(expected = IllegalArgumentException.class)
public void shouldThrowOnSubListOnNonEmptyWhenBeginIndexIsGreaterThanEndIndex() {
of('1', '2', '3').subList(1, 0);
}
@Test(expected = IllegalArgumentException.class)
public void shouldThrowOnSubListOnEmptyWhenBeginIndexIsGreaterThanEndIndex() {
empty().subList(1, 0);
}
@Test(expected = IndexOutOfBoundsException.class)
public void shouldThrowOnSubListOnNonEmptyWhenBeginIndexExceedsLowerBound() {
of('1', '2', '3').subList(-1, 2);
}
@Test(expected = IndexOutOfBoundsException.class)
public void shouldThrowOnSubListOnEmptyWhenBeginIndexExceedsLowerBound() {
empty().subList(-1, 2);
}
@Test(expected = IndexOutOfBoundsException.class)
public void shouldThrowWhenSubList2OnEmpty() {
empty().subList(0, 1);
}
@Test(expected = IndexOutOfBoundsException.class)
public void shouldThrowOnSubListWhenEndIndexExceedsUpperBound() {
of('1', '2', '3').subList(1, 4).size(); // force computation of last element, e.g. for lazy delegate
}
@Test(expected = IllegalArgumentException.class)
public void shouldThrowOnSubListWhenBeginIndexIsGreaterThanEndIndex() {
of('1', '2', '3').subList(2, 1).size(); // force computation of last element, e.g. for lazy delegate
}
@Test
public void shouldReturnEqualInstanceIfSubListStartsAtZeroAndEndsAtLastElement() {
assertThat(of('1', '2', '3').subList(0, 3)).isEqualTo(asList('1', '2', '3'));
}
// -- toArray()
@Test
public void shouldConvertEmptyToArray() {
assertThat(empty().toArray()).isEqualTo(new Object[0]);
}
@Test
public void shouldConvertNonEmptyToArray() {
assertThat(of('1').toArray()).isEqualTo(new Object[] { '1' });
}
// -- toArray(T[])
@Test
public void shouldThrowNPEWhenCallingToArrayNullWhenEmpty() {
assertThatThrownBy(() -> empty().toArray(null))
.isInstanceOf(NullPointerException.class);
}
@Test
public void shouldThrowNPEWhenCallingToArrayNullWhenNotEmpty() {
assertThatThrownBy(() -> of('1').toArray(null))
.isInstanceOf(NullPointerException.class);
}
@Test
public void shouldConvertEmptyToArrayPassingArrayOfCorrectSize() {
assertThat(this.<Character> empty().toArray(new Character[0])).isEqualTo(new Character[0]);
}
@Test
public void shouldConvertEmptyToArrayPassingArrayOfGreaterSize() {
assertThat(this.<Character> empty().toArray(new Character[] { 'x' })).isEqualTo(new Character[] { null });
}
@Test
public void shouldConvertNonEmptyToArrayPassingArrayOfCorrectSize() {
assertThat(of('1', '2').toArray(new Character[2])).isEqualTo(new Character[] { '1', '2' });
}
@Test
public void shouldConvertNonEmptyToArrayPassingArrayOfGreaterSize() {
assertThat(of('1', '2').toArray(new Character[] { 'a', 'b', 'c', 'd' })).isEqualTo(new Character[] { '1', '2', null, 'd' });
}
@Test
public void shouldConvertNonEmptyToArrayPassingArrayOfSmallerSize() {
assertThat(of('1', '2').toArray(new Character[1])).isEqualTo(new Character[] { '1', '2' });
}
// --- helpers
@SuppressWarnings("varargs")
@SafeVarargs
private final void ifSupported(Runnable test, Class<? extends Throwable>... expectedExceptionTypes) {
try {
test.run();
if (changePolicy == IMMUTABLE) {
Assert.fail("Operation should throw " + UnsupportedOperationException.class.getName());
}
if (expectedExceptionTypes.length > 0) {
Assert.fail("Expected one of " + List.of(expectedExceptionTypes).map(Class::getName).mkString("[", ", ", "]"));
}
} catch (Throwable x) {
if (changePolicy == IMMUTABLE) {
if (!(x instanceof UnsupportedOperationException)) {
final boolean isJavaCollection = empty().getClass().getName().startsWith("java.util.");
// DEV-NOTE: Java's collections throw UnsupportedOperationException inconsistently
if (!isJavaCollection) {
Assert.fail("Operation should throw " + UnsupportedOperationException.class.getName() + " but found " + x.getClass().getName() + ":\n" + x.getMessage());
}
}
} else {
final Class<? extends Throwable> actualType = x.getClass();
for (Class<? extends Throwable> expectedType : expectedExceptionTypes) {
if (expectedType.isAssignableFrom(actualType)) {
return;
}
}
throw x;
}
}
}
static final class ListFactory {
private final Function<Object[], java.util.List<Object>> listFactory;
ListFactory(Function<Object[], java.util.List<Object>> listFactory) {
this.listFactory = listFactory;
}
@SuppressWarnings("unchecked")
<T> java.util.List<T> of(T... elements) {
return (java.util.List<T>) listFactory.apply(elements);
}
}
enum ChangePolicy {
IMMUTABLE, MUTABLE;
}
enum ElementType {
FIXED, GENERIC;
}
enum ElementNullability {
NULLABLE, NON_NULLABLE;
}
}